﻿using System;
using System.Collections.Generic;
using System.Text;
using CommandLine;
using CommandLine.Text;
using Microsoft.Win32.TaskScheduler;

namespace SchTasksSetPriority
{
    /// <summary>
    /// The entry point for the program.
    /// </summary>
    class Program
    {
        /// <summary>
        /// The entry point for the console application.
        /// </summary>
        /// <param name="args">The arguments.</param>
        /// <returns><c>0</c>, success; otherwise, <c>1</c> failure.</returns>
        static int Main(string[] args)
        {
            try
            {
                var options = new Options();
                if (CommandLineParser.Default.ParseArguments(args, options))
                {
                    bool setPriority = !string.IsNullOrEmpty(options.Priority);
                    System.Diagnostics.ProcessPriorityClass priority = System.Diagnostics.ProcessPriorityClass.BelowNormal;
                    if (setPriority)
                    {
                        if (Enum.IsDefined(typeof(System.Diagnostics.ProcessPriorityClass), options.Priority))
                        {
                            priority = (System.Diagnostics.ProcessPriorityClass)Enum.Parse(typeof(System.Diagnostics.ProcessPriorityClass), options.Priority);
                        }
                        else
                        {
                            Console.WriteLine("Error: The priority is invalid. Valid values for priority are {0}.", Options.GetPriorityValues());
                            return 1;
                        }
                    }

                    using (var service = new TaskService(options.Server ?? ""))
                    {
                        var taskName = options.TaskName;
                        TaskFolder parentFolder;
                        Task task = null;
                        if (taskName.Contains(@"\"))
                        {
                            var taskNameParts = taskName.Split('\\');
                            parentFolder = service.GetFolder(taskNameParts[0]);
                            for (int i = 1; i < (taskNameParts.Length - 1); i++)
                            {
                                var folderName = taskNameParts[i];
                                parentFolder = parentFolder.SubFolders[folderName];
                                if (parentFolder == null)
                                {
                                    Console.WriteLine("Tasks path is invalid. The task name indicates it's within a folder which doesn't exist. Task Folder: {0}", folderName);
                                    return 1;
                                }
                            }
                            taskName = taskNameParts[taskNameParts.Length - 1];
                        }
                        else
                        {
                            parentFolder = service.GetFolder("");
                            if (parentFolder == null)
                            {
                                Console.WriteLine("No root folder exists. Tried to access the root task folder but it didn't exist.");
                                return 1;
                            }
                        }
                        foreach (var possibleTask in parentFolder.GetTasks())
                        {
                            if (string.Equals(possibleTask.Name, taskName, StringComparison.InvariantCultureIgnoreCase))
                            {
                                task = possibleTask;
                                break;
                            }
                        }
                        if (task == null)
                        {
                            Console.WriteLine("Task not found. The task name provided could not be found. Task Name: {0}", taskName);
                            return 1;
                        }

                        if (setPriority)
                        {
                            // set the priority of the task
                            var originalPriority = task.Definition.Settings.Priority;
                            task.Definition.Settings.Priority = priority;
                            
                            // we have to re-register the task definition because it provides us the way
                            // to pass the user and password to the task
                            // else
                            // nasty security errors
                            parentFolder.RegisterTaskDefinition(taskName, task.Definition, TaskCreation.Update | TaskCreation.IgnoreRegistrationTriggers, options.TaskRunAsUser, options.TaskRunAsPassword, task.Definition.Principal.LogonType);

                            // let the user know we did it
                            Console.WriteLine("Task {0}: Priority changed from {1} to {2}.", options.TaskName, originalPriority, task.Definition.Settings.Priority);
                        }
                        else
                        {
                            // just output the current priority.
                            Console.WriteLine("Task {0}: The priority is {1}.", options.TaskName, task.Definition.Settings.Priority);
                        }
                    }
                }
                return 0;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Unhandled exception occurred.\n\n{0}", ex);
                return 1;
            }
        }
    }
}
